/**
 * 
 */
package com.example.gametestproject;

import java.util.Random;
import java.util.Vector;

import android.util.Log;
import android.graphics.PointF;
import android.graphics.RectF;

import com.xxxx.game.*;

/**
 * @author HuXiaolong
 *
 */
public abstract class IGameMode implements IAction
{
	protected int mLastSpriteIndex = -1;
	protected final static int STEP_TIME = 7;
	private Vector<ISprite> mFreshSprites = new Vector<ISprite>();
	private Vector<ISprite> mDeadSprites = new Vector<ISprite>();
	protected int mComboTime = 0;
	protected GameLevel mLevel;
	
	public JewelSprite getSelectedJewel(GameMatrix gm)
	{
		gm = this.mLevel.mMatrix;
		if (mLastSpriteIndex != -1)
		{
			return gm.getJewelSprites()[mLastSpriteIndex / gm.getCols()][mLastSpriteIndex % gm.getCols()];
		}
		
		return null;
	}
	
	/* (non-Javadoc)
	 * @see com.example.gametestproject.IAction#doAction(java.util.Vector, android.view.MotionEvent)
	 */
	@Override
	public void doAction(GameMatrix gm, PointF ptStart, MotionType type)
	{
		// TODO Auto-generated method stub
		throw new RuntimeException("not implement");
	}
	
	public boolean isStop()
	{
		return false;
	}

	protected boolean canExchange(GameMatrix gm, int idx1, int idx2)
	{
		gm = this.mLevel.mMatrix;
		if (gm.getRows() * gm.getCols() <= Math.min(idx1, idx2) ||
				idx1 < 0 || idx2 < 0)
		{
			Log.i("IGameMode", String.format("invalidate index %d and %d", idx1, idx2));
			return false;
		}
		
		JewelSprite[][] jewels = gm.getJewelSprites();
		JewelSprite js1 = jewels[idx1/gm.getCols()][idx1%gm.getCols()];
		JewelSprite js2 = jewels[idx2/gm.getCols()][idx2%gm.getCols()];
		
		if (js1 == null || js2 == null) return false;
		
		//Log.i("IGameMode", String.format("check to exchage %d(%d,%d) and %d(%d,%d)", 
		//		idx1, js1.getRow(), js1.getCol(), idx2, js2.getRow(), js2.getCol()));
		if (js1.isMoving() || js2.isMoving() || // one jewlel is moving 
				js1.getJewelType() == js2.getJewelType() || // or two jewels is same type
				js1.getLiveMode() != 0 || js2.getLiveMode() != 0 || // js is dying or dead
				Math.abs(js1.getRow() - js2.getRow()) + Math.abs(js1.getCol() - js2.getCol()) != 1)
		{
		//	Log.i("IGameMode", "check failed!");
			return false;
		}
		// check can exchange
		return canExchange(jewels, js2.getCol(), js2.getRow(), js1.getJewelType(), js1.getCol(), js1.getRow()) || // move jewlel-1 to new position
				canExchange(jewels, js1.getCol(), js1.getRow(), js2.getJewelType(), js2.getCol(), js2.getRow());  // move jewlel-2 to new position
	}
	
	protected boolean canExchange(JewelSprite[][] jewels, int x, int y, int type, int xorg, int yorg)
	{
		// horz
		int w = 1;
		for (int xi = x - 1; xi >= 0 && jewels[y][xi] != null &&
				jewels[y][xi].getJewelType() == type && jewels[y][xi].getLiveMode() == 0; -- xi) 
		{
			if (xi == xorg && y == yorg) break; // not orginal position
			++ w;
		}
		if (w >= 3) return true;
		for (int xi = x + 1; xi < jewels[y].length && jewels[y][xi] != null &&
				jewels[y][xi].getJewelType() == type && jewels[y][xi].getLiveMode() == 0; ++ xi)
		{
			if (xi == xorg && y == yorg) break; // not orginal position
			++ w;
		}
		if (w >= 3) return true;
				
		// vert
		int h = 1;
		for (int yi = y - 1; yi >= 0 && jewels[yi][x] != null &&
				jewels[yi][x].getJewelType() == type && jewels[yi][x].getLiveMode() == 0; -- yi)
		{
			if (x == xorg && yi == yorg) break; // not orginal position
			++ h;
		}
		if (h >= 3) return true;
		for (int yi = y + 1; yi < jewels.length && jewels[yi][x] != null &&
				jewels[yi][x].getJewelType() == type && jewels[yi][x].getLiveMode() == 0; ++ yi)
		{
			if (x == xorg && yi == yorg) break; // not orginal position
			++ h;
		}
		if (h >= 3) return true;
		
		return false;
	}
	
	//change position of two sprite, this will cause move animation
	protected void swapSprite(GameMatrix gm, int index1, int index2)
	{
		gm = this.mLevel.mMatrix;
		JewelSprite[][] jewels = gm.getJewelSprites();
		JewelSprite js1 = jewels[index1/gm.getCols()][index1%gm.getCols()];
		JewelSprite js2 = jewels[index2/gm.getCols()][index2%gm.getCols()];
		
		Log.i("IGameMode", String.format("exchanage jewel (%d, %d) and (%d, %d)", js1.getRow(), js1.getCol(), js2.getRow(), js2.getCol()));
		PointF pos1 = js1.getPosition();
		PointF pos2 = js2.getPosition();
		
		int stepCount = Math.max(Math.abs(js1.getCol() - js2.getCol()), 
				Math.abs(js1.getRow() - js2.getRow())) * STEP_TIME;
		
//		js1.appendAnimation(new LinearPath(pos1, pos2, stepCount));
//		js2.appendAnimation(new LinearPath(pos2, pos1, stepCount));
		IAnimation anim = js1.findAnimation("Move");
		if (anim != null) anim.append(new LinearPath(pos1, pos2, stepCount));
		else js1.combineAnimation(new LinearPath(pos1, pos2, stepCount));
		
		anim = js2.findAnimation("Move");
		if (anim != null) anim.append(new LinearPath(pos1, pos2, stepCount));
		else js2.combineAnimation(new LinearPath(pos2, pos1, stepCount));
		
		jewels[index1/gm.getCols()][index1%gm.getCols()] = js2;
		jewels[index2/gm.getCols()][index2%gm.getCols()] = js1;
		
		js1.setCol(index2 % gm.getCols());
		js1.setRow(index2 / gm.getCols());
		
		js2.setCol(index1 % gm.getCols());
		js2.setRow(index1 / gm.getCols());
		
		// reset z-order
		int zorder = js1.getZOrder();
		js1.setZOrder(js2.getZOrder());
		js2.setZOrder(zorder);
		js1.setSelected(false);
		js2.setSelected(false);
	}
	
	@Override
	public int vanishSpites(GameMatrix gm)
	{
		gm = this.mLevel.mMatrix;
		int rows = gm.getRows();
		int cols = gm.getCols();
		int ivcount = 0;
		
		JewelSprite[][] jewels = gm.getJewelSprites();
		// easy check now, don't 
		int []vercc = new int[cols];
		for (int i = 0; i < vercc.length; ++ i)
		{
			vercc[i] = 0;
		}
		for (int y = 0; y < rows; ++ y)
		{
			int horcc = 0;
			for (int x = 0; x < cols; ++ x)
			{
				if (jewels[y][x] == null || jewels[y][x].isMoving() || jewels[y][x].getLiveMode() != ISprite.ISPRITE_STATE_LIVE)
				{ // dead or is moving
					ivcount += checkHorz(jewels, horcc, x - 1, y);
					ivcount += checkVerc(jewels, vercc[x], x, y - 1);
					horcc = 0;
					vercc[x] = 0;
					continue;
				}
				
				// check horz
				if (horcc > 0 && jewels[y][x].getJewelType() == jewels[y][x - 1].getJewelType())
				{
					++ horcc;
				}
				else 
				{
					ivcount += checkHorz(jewels, horcc, x - 1, y);
					horcc = 1;
				}
				
				// check verc
				if (vercc[x] > 0 && jewels[y][x].getJewelType() == jewels[y - 1][x].getJewelType())
				{
					++ vercc[x];
				}
				else
				{
					ivcount += checkVerc(jewels, vercc[x], x, y - 1);
					vercc[x] = 1;
				}
			}
			ivcount += checkHorz(jewels, horcc, cols - 1, y);
		}
		
		for (int i = 0; i < cols; ++ i)
		{
			ivcount += checkVerc(jewels, vercc[i], i, rows - 1);
		}
		
		return ivcount;
	}
	
	private int checkHorz(JewelSprite[][] jewels, int horcc, int x, int y)
	{
		if (horcc < 3) return 0;
		int count = horcc;
		// mark left sprites dying
		Vector<JewelSprite> vec = new Vector<JewelSprite>();
		for (int i = x; horcc != 0; -- i, -- horcc)
		{
			vec.add(jewels[y][i]);
			// add score
//			PointF ptStart = this.getSpritePosistion(i, y);
//			ptStart.x += ResourceManager.mSpriteWidth / 2;
//			ptStart.y += ResourceManager.mSpriteHeight / 2;
//			PointF ptEnd =  new PointF(ptStart.x, 
//					ptStart.y - ResourceManager.mSpriteHeight / 2);
//			TextSprite ts = new ScoreSprite("+10", ptStart, ptEnd);
//			this.addSprite(ts);
			//this.addTextSprite(jewels[y][i], 10*this.mComboTime);
		}
		this.markSpritesDying(vec, 2, jewels);
		return count;
	}
	
	private int checkVerc(JewelSprite[][] jewels, int vercc, int x, int y)
	{
		if (vercc < 3) return 0;
		int count = vercc;
		// mark top sprites dying
		Vector<JewelSprite> vec = new Vector<JewelSprite>();
		for (int i = y; vercc != 0; -- i, -- vercc)
		{
			vec.add(jewels[i][x]);
		}
		this.markSpritesDying(vec, 2, jewels);
		return count;
		
	}
	
	@Override
	public int insertRemoveJewels(GameMatrix gm, Vector<ISprite> freshSprites, Vector<ISprite> vanishSprites)
	{
		gm = this.mLevel.mMatrix;
		int hole[] = new int[gm.getCols()];
		for (int i = 0; i < hole.length; ++ i)
		{
			hole[i] = 0;
		}
		
		JewelSprite[][] jewels = gm.getJewelSprites();
		for (int y = gm.getRows() - 1; y >= 0; -- y)
		{
			for (int x = 0; x < gm.getCols(); ++ x)
			{
				if (jewels[y][x].getLiveMode() == ISprite.ISPRITE_STATE_LIVE || jewels[y][x].getLiveMode() == ISprite.ISPRITE_STATE_DYING)
				{
					if (hole[x] != 0)
					{ // add path
						jewels[y + hole[x]][x] = jewels[y][x];
						// goto down
						LinearPath path = new LinearPath(getSpritePosistion(x, y), 
								getSpritePosistion(x, y + hole[x]), STEP_TIME * hole[x]);
						
						IAnimation anim = jewels[y][x].findAnimation("Move");
						if (anim != null) anim.append(path);
						else jewels[y][x].combineAnimation(path);
                        jewels[y][x].combineAnimation(new BounceAnimation(path.getEndPoint(), BounceAnimation.UP_DISTANCE,BounceAnimation.STEP),path.getStepCount());
						jewels[y][x].setRow(y + hole[x]);
						jewels[y][x].setZOrder(JewelSprite.jewel_zorder + (y +  + hole[x]) * gm.getCols() + x);
						jewels[y][x] = null;
					}
				}
				//else if(jewels[y][x].getLiveMode() == 1)
				//{ // do nothing
				//	hole[x] = 0;
				//}
				else
				{
					++ hole[x];
					this.removeSprite(jewels[y][x]);
					jewels[y][x] = null;
				}
			}
		}
		Random random = new Random(System.currentTimeMillis());
		for (int x = 0; x < hole.length; ++ x)
		{
			for (int i = 0; i < hole[x]; ++ i)
			{
				int jstype = random.nextInt(ResourceManager.getInstance().getSpriteBitmapCount());
				JewelSprite sprite = new JewelSprite(jstype, jstype, i, x);
				jewels[i][x] = sprite;
				sprite.setPosition(getSpritePosistion(x, i));
				sprite.setZOrder(JewelSprite.jewel_zorder + i * gm.getCols() + x);
				
				this.addSprite(sprite);
				
				Log.i("jewel", String.format("insert new jewel @(%d, %d)", i, x));
				
				LinearPath path = new LinearPath(getSpritePosistion(x, i - hole[x] - 1), 
						getSpritePosistion(x, i), STEP_TIME * (hole[x] + 1));
				sprite.appendAnimation(path);
                sprite.combineAnimation(new BounceAnimation(path.getEndPoint(), BounceAnimation.UP_DISTANCE, BounceAnimation.STEP), path.getStepCount());
//				sprite.combineAnimation(path);
			}
		}
		
		freshSprites.addAll(this.mFreshSprites);
		vanishSprites.addAll(this.mDeadSprites);
		
		this.mFreshSprites.clear();
		this.mDeadSprites.clear();
		return 0;
	}
	
	private PointF getSpritePosistion(int x, int y)
	{
		return new PointF(MapManager.getInstance().mLeftPadding + x * ResourceManager.mSpriteWidth, 
				MapManager.getInstance().mTopPadding + y * ResourceManager.mSpriteHeight);
	}
	
	public JewelSprite getJewelAtPoint(GameMatrix gm, float xcord, float ycord)
	{
		gm = this.mLevel.mMatrix;
		int idx = getRowandColAtPoint(xcord, ycord);
		if (gm != null && gm.getJewelSprites() != null)
		{
			return gm.getJewelSprites()[idx/gm.getCols()][idx%gm.getCols()];
		}
		return null;
	}
	
	protected int getRowandColAtPoint(float xcord, float ycord)
	{	
		int getJewelIdx = -1;
		MapManager lpInstance = MapManager.getInstance();
		if (xcord >= lpInstance.mLeftPadding && xcord < ResourceManager.mScreenWidth - lpInstance.mRightPadding &&
				ycord >= lpInstance.mTopPadding && ycord < ResourceManager.mScreenHeight - lpInstance.mBottomPadding)
		{
			//int y = lpInstance.mRows - (int)((ycord- lpInstance.mBottomPadding) / ResourceManager.mSpriteHeight) - 1;
			int y = (int)(ycord- lpInstance.mTopPadding) / ResourceManager.mSpriteHeight;
			int x = (int)((xcord- lpInstance.mLeftPadding) / ResourceManager.mSpriteWidth);
			
			getJewelIdx = y * MapManager.getInstance().mColumns + x;
			Log.i("action", String.format("selecte jewle(%d, %d), idx(%d)", y, x, getJewelIdx));
		}
		return getJewelIdx;
	}
	
	public boolean isGameOver(GameMatrix gm)
	{
		gm = this.mLevel.mMatrix;
		int rows = gm.getRows();
		int cols = gm.getCols();

		JewelSprite[][] jewels = gm.getJewelSprites();
		
		// some one is hole or is moving
		for (int y = 0; y < rows; ++ y)
			for (int x = 0; x < cols; ++ x)
				if (jewels[y][x] == null || jewels[y][x].isMoving() || jewels[y][x].getLiveMode() != ISprite.ISPRITE_STATE_LIVE) 
					return false;
		
		for (int y = 0; y < rows; ++ y)
		{
			for (int x = 0; x < cols; ++ x)
			{
				// try to exchange with right jewel
				if (x != cols - 1 && jewels[y][x + 1].getJewelType() != jewels[y][x].getJewelType() &&
						(this.canExchange(jewels, x + 1, y, jewels[y][x].getJewelType(), x, y) ||
								this.canExchange(jewels, x, y, jewels[y][x + 1].getJewelType(), x + 1, y)))
					return false;
				
				// try to exchange with up jewel
				if (y != 0 && jewels[y - 1][x].getJewelType() != jewels[y][x].getJewelType() &&
						(this.canExchange(jewels, x, y - 1, jewels[y][x].getJewelType(), x, y) ||
								this.canExchange(jewels, x, y, jewels[y - 1][x].getJewelType(), x, y - 1)))
					return false;
				
			}
		}
		return true;
	}
	
	public boolean isLevelOver()
	{
		return this.mLevel.isLevelOver();
	}
	
	public boolean getHint(GameMatrix gm, int []sprites)
	{
		gm = this.mLevel.mMatrix;
		int rows = gm.getRows();
		int cols = gm.getCols();
		
		int curidx = 0;
		for (int y = 0; y < rows; ++ y)
		{
			for (int x = 0; x < cols; ++ x)
			{
				if (x != cols - 1 && this.canExchange(gm, curidx, curidx + 1))
				{
					sprites[0] = curidx;
					sprites[1] = curidx + 1;
					return true;
				}
				else if (y != 0 && this.canExchange(gm, curidx, curidx - cols))
				{
					sprites[0] = curidx;
					sprites[1] = curidx - cols;
					return true;
				}
				++ curidx;
			}
		}
		return false;
	}
	
	@Override
	public void addSprite(ISprite sprite)
	{
		mFreshSprites.add(sprite);
	}

	@Override
	public void removeSprite(ISprite sprite)
	{
		mDeadSprites.add(sprite);
	}
	
	private void markSpritesDying(Vector<JewelSprite> sprites, int anchorIdx, JewelSprite[][] spriteMatrix)
	{
		this.mComboTime ++;
		this.mLevel.addComboTimes();
		if(this.checkSpriteState(sprites))//if one dog is on fire or flash state
		{
			this._markSpritesDying(sprites, spriteMatrix);
		}
		else
		{
			int count = sprites.size();
			switch(count)
			{
				case 3://3 sprites
					for(int idx = 0; idx < sprites.size(); ++ idx)
					{
						JewelSprite js = sprites.get(idx);
						js.setLiveMode(ISprite.ISPRITE_STATE_DYING);
						Log.i("jewel", String.format("mark (%d,%d) dying", js.getRow(), js.getCol()));
						
						SpriteVanishAnimation va = new SpriteVanishAnimation(
								ResourceManager.getInstance().getFramesOfAnimation(
										ResourceManager.getInstance().Vanish_Amin, js.getJewelType()),
								10);
						js.combineAnimation(va);
						//js.combineAnimation(new ShakeAnimation(js.getPosition(), 2, 2));
						js.setDrawFunc(va);
						
						// add score
//						PointF ptStart = this.getSpritePosistion(js.getCol(), js.getRow());
//						ptStart.x += ResourceManager.mSpriteWidth / 2;
//						ptStart.y += ResourceManager.mSpriteHeight / 2;
//						PointF ptEnd =  new PointF(ptStart.x, 
//											ptStart.y - ResourceManager.mSpriteHeight / 2);
//						TextSprite ts = new ScoreSprite("+10", ptStart, ptEnd);
//						this.addSprite(ts);
						this.addTextSprite(js, 10 * this.mComboTime);
					}
					break;
				case 4://4 sprites
					anchorIdx = 2;
					PointF anchorSpritePos = sprites.get(anchorIdx).getPosition();
					for(int idx = 0; idx < sprites.size(); ++idx)
					{
						if(idx != anchorIdx)
						{
							JewelSprite js = sprites.get(idx);
							js.setLiveMode(ISprite.ISPRITE_STATE_DYING);
							Log.i("jewel", String.format("mark (%d,%d) dying", js.getRow(), js.getCol()));
							LinearPath path = new LinearPath(sprites.get(idx).getPosition(), 
									anchorSpritePos, 10);//attention this is hard code.
							js.combineAnimation(new ShakeAnimation(js.getPosition(), 3, 3));
							js.combineAnimation(path, 8);
							js.combineAnimation(new MakedeadAnimation(10 + 8));
							//add score
							this.addTextSprite(js, 10 * this.mComboTime);
						}	
					}
					FrameAnimation fireAnim = new FrameAnimation(ResourceManager.getInstance().getFramesOfAnimation(ResourceManager.getInstance().Fire_Anim, 0), 0, true);
					sprites.get(anchorIdx).combineAnimation(fireAnim, 10);
					sprites.get(anchorIdx).addNewDrawing(new DelayDrawing(10 + 18, fireAnim), "basicdrawing");
					sprites.get(anchorIdx).setState(JewelState.JewelState_Fire);
					this.addTextSprite(sprites.get(anchorIdx), 10 * this.mComboTime);
					break;
				case 5://5 sprites
					anchorIdx = 2;
					PointF anchorSpritePos2 = sprites.get(anchorIdx).getPosition();
					for(int idx = 0; idx < sprites.size(); ++idx)
					{
						if(idx != anchorIdx)
						{
							JewelSprite js = sprites.get(idx);
							js.setLiveMode(ISprite.ISPRITE_STATE_DYING);
							Log.i("jewel", String.format("mark (%d,%d) dying", js.getRow(), js.getCol()));
							LinearPath path = new LinearPath(sprites.get(idx).getPosition(), 
									anchorSpritePos2, 10);//attention this is hard code.
							js.combineAnimation(new ShakeAnimation(js.getPosition(), 3, 3));
							js.combineAnimation(path, 8);//time for shakeAnimation is 10
							js.combineAnimation(new MakedeadAnimation(10 + 8));
							//add score
							this.addTextSprite(js, 10 * this.mComboTime);
						}	
					}
					FrameAnimation flashAnim = new FrameAnimation(ResourceManager.getInstance().getFramesOfAnimation(ResourceManager.getInstance().Flash_Anim, 0), 0, true);
					sprites.get(anchorIdx).combineAnimation(flashAnim, 10);
					sprites.get(anchorIdx).addNewDrawing(new DelayDrawing(10 + 18, flashAnim), "basicdrawing");
					sprites.get(anchorIdx).setState(JewelState.JewelState_Flash);
					this.addTextSprite(sprites.get(anchorIdx), 10 * this.mComboTime);
					
					PointF ptStart = this.getSpritePosistion(sprites.get(anchorIdx).getCol(), 
							sprites.get(anchorIdx).getRow());
					ptStart.x += ResourceManager.mSpriteWidth / 2;
					ptStart.y += ResourceManager.mSpriteHeight / 2;
					PointF ptEnd =  new PointF(ptStart.x, 
										ptStart.y - ResourceManager.mSpriteHeight);
					ShaderTextSprite sts = new ShaderTextSprite("Good", ptStart, ptEnd);
					this.addSprite(sts);
					break;	
			}	
		}
	}
	private boolean checkSpriteState(Vector<JewelSprite> sprites)//
	{
		for(int index = 0; index < sprites.size(); ++index)
		{
			if(sprites.get(index).getState() != JewelState.JewelState_Normal)
				return true;
		}
		return false;
	}
	
	private void _markSpritesDying(Vector<JewelSprite> sprites, JewelSprite[][] spriteMatrix)
	{
		for(int count = 0; count < sprites.size(); ++count)
		{
			if(sprites.get(count).getState() != JewelState.JewelState_Normal)
			{
				this._markSpritesDying(sprites.get(count), spriteMatrix);
			}
		}
		
		for(int count = 0; count < sprites.size(); ++count)
		{
			if(sprites.get(count).getLiveMode() != ISprite.ISPRITE_STATE_DYING)
			{
				this.addTextSprite(sprites.get(count), 10 * this.mComboTime);
				sprites.get(count).setLiveMode(ISprite.ISPRITE_STATE_DYING);
				sprites.get(count).getPaint().setAlpha(0);
				sprites.get(count).combineAnimation(new MakedeadAnimation(ResourceManager.getInstance().getFrameNumOfAnimation(ResourceManager.getInstance().Explosion_Anim)));
			}
		}
	}
	
	private void _markSpritesDying(JewelSprite sprite, JewelSprite[][] spriteMatrix)
	{
		ResourceManager RManager = ResourceManager.getInstance(); 
		int maxRow = spriteMatrix.length;
		int maxCol = spriteMatrix[0].length;
		if(sprite.getState() == JewelState.JewelState_Fire)//fire
		{
			sprite.setState(JewelState.JewelState_Normal);
			Vector<Integer> explosionFrm = RManager.getFramesOfAnimation(RManager.Explosion_Anim, 0);
			int[][] directions = {{-1, -1}, {-1, 0}, {-1, 1},
					  {0, -1},{0, 0}, {0, 1},
					  {1, -1}, {1, 0}, {1, 1}};
			int row = sprite.getRow();
			int col = sprite.getCol();
			RectF neighbourRect = sprite.getRect();
			for(int i = 0; i < directions.length; ++i)	
			{
				int irow = row + directions[i][0];
				int icol = col + directions[i][1];
				if(isValidPos(irow, icol, maxRow, maxCol))//make all 3*3 neighbors dying
				{
					if(spriteMatrix[irow][icol].getState() != JewelState.JewelState_Normal)
					{
						_markSpritesDying(spriteMatrix[irow][icol], spriteMatrix);
					}
					else
					{
						if(spriteMatrix[irow][icol].getLiveMode() != ISprite.ISPRITE_STATE_DYING)
							this.addTextSprite(spriteMatrix[irow][icol], 10 * this.mComboTime);
						spriteMatrix[irow][icol].setLiveMode(ISprite.ISPRITE_STATE_DYING);
						spriteMatrix[irow][icol].getPaint().setAlpha(0);
						spriteMatrix[irow][icol].combineAnimation(new MakedeadAnimation(explosionFrm.size()));
						RectF irect = spriteMatrix[irow][icol].getRect();
						neighbourRect.left = (neighbourRect.left < irect.left) ? neighbourRect.left : irect.left;
						neighbourRect.right = (neighbourRect.right > irect.right) ? neighbourRect.right : irect.right;
						neighbourRect.top = (neighbourRect.top < irect.top) ? neighbourRect.top : irect.top;
						neighbourRect.bottom = (neighbourRect.bottom > irect.bottom) ? neighbourRect.bottom : irect.bottom;
					}
				}
			}
			FrameAnimation flashAnim = new FrameAnimation(ResourceManager.getInstance().getFramesOfAnimation(ResourceManager.getInstance().Explosion_Anim, 0),neighbourRect);
			sprite.combineAnimation(flashAnim, 0);
			sprite.addNewDrawing(flashAnim, "basicdrawing");
		}
		else{//flash
			sprite.setState(JewelState.JewelState_Normal);
			Vector<Integer> flushFrm = RManager.getFramesOfAnimation(RManager.FlushDis_Anim, 0);
			int row = sprite.getRow();
			int col = sprite.getCol();
			for(int i = 0; i < spriteMatrix.length; ++i)
			{
				if(spriteMatrix[i][col].getState() != JewelState.JewelState_Normal)
				{
					_markSpritesDying(spriteMatrix[i][col], spriteMatrix);
				}
				else
				{
					if(spriteMatrix[i][col].getLiveMode() != ISprite.ISPRITE_STATE_DYING)
						this.addTextSprite(spriteMatrix[i][col], 10 * this.mComboTime);
					spriteMatrix[i][col].setLiveMode(ISprite.ISPRITE_STATE_DYING);
					spriteMatrix[i][col].getPaint().setAlpha(0);
					spriteMatrix[i][col].combineAnimation(new MakedeadAnimation(ResourceManager.getInstance().getFramesOfAnimation(ResourceManager.getInstance().FlushDis_Anim, 0).size()));
					
				}
			}
			RectF nrect = spriteMatrix[spriteMatrix.length / 2][col].getRect();
			FrameAnimation flushAnim = new FrameAnimation(ResourceManager.getInstance().getFramesOfAnimation(ResourceManager.getInstance().FlushDis_Anim, 0), nrect);
			sprite.combineAnimation(flushAnim, 0);
			sprite.addNewDrawing(flushAnim, "basicdrawing");
		}

	}
	private boolean isValidPos(int irow, int icol, int maxRow, int maxCol)
	{
		return (irow >= 0 && irow < maxRow && icol >= 0 && icol < maxCol);
	}
	private void addTextSprite(JewelSprite sprite, int score)
	{	
		this.mLevel.addUserScore(score);//increase user score;
		PointF ptStart = this.getSpritePosistion(sprite.getCol(), sprite.getRow());
		ptStart.x += ResourceManager.mSpriteWidth / 2;
		ptStart.y += ResourceManager.mSpriteHeight / 2;
		PointF ptEnd =  new PointF(ptStart.x,
						ptStart.y - ResourceManager.mSpriteHeight / 2);
		TextSprite ts = new ScoreSprite("+" + score, ptStart, ptEnd);
		this.addSprite(ts);
		
	}
	public void setGameLevel(GameLevel ilevel)
	{
		this.mLevel = ilevel;
	}
	public GameLevel getLevel()
	{
		return this.mLevel;
	}
	public void gotoNextLevel()
	{
		this.mDeadSprites.clear();
		this.mFreshSprites.clear();
		this.mComboTime = 0;
		this.mLevel.nextLevel();
		
		ShaderTextSprite sts = new ShaderTextSprite("Next Level", new PointF(ResourceManager.mScreenWidth / 2,
				ResourceManager.mScreenHeight / 2), new PointF(ResourceManager.mScreenWidth / 2 + 20,
						ResourceManager.mScreenHeight / 2 + 20));
		sts.setLiveTime(60);
		this.addSprite(sts);
	}
}
